/*
 * Copyright (C) 2018 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.xuexiang.xdlink;

import android.content.Context;
import android.support.annotation.NonNull;

import com.xuexiang.xdlink.component.buffer.IBuffer;
import com.xuexiang.xdlink.component.buffer.impl.CircularBuffer;
import com.xuexiang.xdlink.component.channel.IChannel;
import com.xuexiang.xdlink.component.channel.entity.ChannelType;
import com.xuexiang.xdlink.component.channel.impl.MockChannel;
import com.xuexiang.xdlink.component.channel.impl.bt.BLEChannel;
import com.xuexiang.xdlink.component.channel.impl.socket.client.ClientSocketChannel;
import com.xuexiang.xdlink.component.channel.impl.usb.FtdiUSBChannel;
import com.xuexiang.xdlink.component.protocol.OnReceivedMessageListener;
import com.xuexiang.xdlink.component.resolver.IMessageResolver;
import com.xuexiang.xdlink.component.resolver.IResolveProxy;
import com.xuexiang.xdlink.component.resolver.impl.SimpleMessageResolver;
import com.xuexiang.xdlink.core.OnDeviceConnectListener;
import com.xuexiang.xdlink.core.OnErrorListener;
import com.xuexiang.xdlink.core.function.IDataSaver;
import com.xuexiang.xdlink.core.function.IMonitor;
import com.xuexiang.xdlink.core.function.impl.ChannelTimeoutMonitor;
import com.xuexiang.xdlink.core.function.impl.DefaultDataSaver;
import com.xuexiang.xdlink.core.impl.DefaultErrorListener;
import com.xuexiang.xdlink.core.impl.DeviceConnectCenter;
import com.xuexiang.xdlink.logs.DCFLog;
import com.xuexiang.xdlink.logs.ILogger;

import java.io.File;

/**
 * Device connection framework（XDLink) API
 *
 * @author xuexiang
 * @since 2018/8/12 下午6:51
 */
public final class XDLink {

    private static volatile XDLink sInstance;

    /**
     * 全局出错的监听【有默认】
     */
    OnErrorListener mOnErrorListener;

    private XDLink() {
        mOnErrorListener = new DefaultErrorListener();
    }

    /**
     * 获取设备连接的入口
     *
     * @return 设备连接的入口
     */
    public static XDLink get() {
        if (sInstance == null) {
            synchronized (XDLink.class) {
                if (sInstance == null) {
                    sInstance = new XDLink();
                }
            }
        }
        return sInstance;
    }

    //======================对外API=============================//

    //==========日志设置==========//

    /**
     * 设置是否是debug模式
     *
     * @param isDebug 是否是debug模式
     * @return
     */
    public XDLink debug(boolean isDebug) {
        DCFLog.debug(isDebug);
        return this;
    }

    /**
     * 设置调试模式【只要tag不为空，就是调试模式】
     *
     * @param tag 日志打印的tag
     * @return
     */
    public XDLink debug(String tag) {
        DCFLog.debug(tag);
        return this;
    }

    /**
     * 设置设备连接日志的自定义实现接口
     *
     * @param logger
     */
    public XDLink setLogger(@NonNull ILogger logger) {
        DCFLog.setLogger(logger);
        return this;
    }

    //==========设备连接构建==========//

    /**
     * 获取设备连接的构建者
     *
     * @param deviceType 设备类型
     * @return 设备连接的构建者
     */
    public static DeviceConnectCenter.Builder newDevice(@NonNull String deviceType) {
        return new DeviceConnectCenter.Builder(deviceType);
    }

    /**
     * 获取设备连接的构建者
     *
     * @param deviceType                设备类型
     * @param channel                   通信通道
     * @param onDeviceConnectListener   设备连接监听
     * @param onReceivedMessageListener 设备消息接收监听
     * @return 设备连接的构建者
     */
    public static DeviceConnectCenter.Builder newDevice(@NonNull String deviceType,
                                                        @NonNull IChannel channel,
                                                        @NonNull OnDeviceConnectListener onDeviceConnectListener,
                                                        @NonNull OnReceivedMessageListener onReceivedMessageListener) {
        return new DeviceConnectCenter.Builder(deviceType)
                .setChannel(channel)
                .setOnDeviceConnectListener(onDeviceConnectListener)
                .setOnReceivedMessageListener(onReceivedMessageListener);
    }

    /**
     * 进行简单的设备连接【无协议】
     *
     * @param deviceType                设备类型
     * @param channel                   通信通道
     * @param onDeviceConnectListener   设备连接监听
     * @param onReceivedMessageListener 设备消息接收监听
     * @return 设备连接的构建者
     */
    public static DeviceConnectCenter connect(@NonNull String deviceType,
                                              @NonNull IChannel channel,
                                              @NonNull OnDeviceConnectListener onDeviceConnectListener,
                                              @NonNull OnReceivedMessageListener onReceivedMessageListener) {
        return newDevice(deviceType, channel, onDeviceConnectListener, onReceivedMessageListener).connect();
    }

    //==========内置默认的通信通道==========//

    /**
     * 获取BLEChannel的构建者
     *
     * @param context
     * @return
     */
    public static BLEChannel.Builder ble(Context context) {
        return new BLEChannel.Builder(context);
    }

    /**
     * 获取FtdiUSBChannel的构建者
     *
     * @param context
     * @return
     */
    public static FtdiUSBChannel.Builder usb(Context context) {
        return new FtdiUSBChannel.Builder(context);
    }

    /**
     * 获取FtdiUSBChannel的构建者
     *
     * @param context
     * @return
     */
    public static FtdiUSBChannel.Builder usb(Context context, int vendorId, int productId) {
        return new FtdiUSBChannel.Builder(context)
                .setVendorId(vendorId)
                .setProductId(productId);
    }

    /**
     * 获取ClientSocketChannel的构建者
     *
     * @param ip
     * @param port
     * @return
     */
    public static ClientSocketChannel.Builder clientSocket(String ip, int port) {
        return new ClientSocketChannel.Builder()
                .setIp(ip)
                .setPort(port);
    }

    /**
     * 获取MockChannel的构建者
     *
     * @param mockFile
     * @return
     */
    public static MockChannel.Builder mock(File mockFile) {
        return new MockChannel.Builder()
                .setMockFile(mockFile);
    }

    /**
     * 获取MockChannel的构建者
     *
     * @param context
     * @param assetFileName
     * @return
     */
    public static MockChannel.Builder mock(Context context, String assetFileName) {
        return new MockChannel.Builder()
                .setAssetFile(context, assetFileName);
    }

    //==========内置默认的缓冲区==========//

    /**
     * 获取默认缓冲区
     */
    public static IBuffer buffer() {
        return new CircularBuffer();
    }

    /**
     * 获取默认缓冲区
     *
     * @param bufferLength 缓冲区的长度
     */
    public static IBuffer buffer(int bufferLength) {
        return new CircularBuffer(bufferLength);
    }

    //==========内置默认的消息解析器==========//

    /**
     * 获取默认的消息解析器
     *
     * @param iResolveProxy 解析代理
     */
    public static IMessageResolver resolver(@NonNull IResolveProxy iResolveProxy) {
        return new SimpleMessageResolver(iResolveProxy);
    }

    //==========内置默认的监控器==========//

    /**
     * 获取默认的通信通道监控器
     *
     * @param channelType 通道的类型
     * @param interval    监控器检查的间期
     * @return
     */
    public static IMonitor monitor(@ChannelType String channelType, long interval) {
        return new ChannelTimeoutMonitor(channelType, interval);
    }

    /**
     * 获取默认的通信通道监控器
     *
     * @param channelType 通道的类型
     * @return
     */
    public static IMonitor monitor(@ChannelType String channelType) {
        return new ChannelTimeoutMonitor(channelType);
    }


    //==========内置默认的数据保存者==========//

    /**
     * 获取默认的数据保存者
     *
     * @param saveDirPath 数据存储的目录
     * @param fileName    数据存储的文件名
     * @return
     */
    public static IDataSaver dataSaver(@NonNull String saveDirPath, @NonNull String fileName) {
        return new DefaultDataSaver(saveDirPath, fileName);
    }

    /**
     * 获取默认的数据保存者
     *
     * @param saveFile 数据存储的文件
     * @return
     */
    public static IDataSaver dataSaver(@NonNull File saveFile) {
        return new DefaultDataSaver(saveFile);
    }

    //==========全局设置==========//

    /**
     * 设置全局出错的监听
     *
     * @param onErrorListener
     * @return
     */
    public XDLink setOnErrorListener(@NonNull OnErrorListener onErrorListener) {
        mOnErrorListener = onErrorListener;
        return this;
    }

}
